﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PetGo
{
    partial class Board
    {
        public static Dictionary<int, int> neis = new Dictionary<int, int>();
        public static List<int> opps = new List<int>();
        public static int lastMove = -1;
        public static Group lastGroup;
        public static List<int> myPlayOutTopMoves = new List<int>();
        public static Dictionary<int, List<int>> ownAroundLastGroup = new Dictionary<int, List<int>>();
        public static Dictionary<int, int> thepatternmove = new Dictionary<int, int>();
        public static Dictionary<int, int> neutrals = new Dictionary<int, int>();
        //public static List<Group> OwntwoLibs = new List<Group>();
        //public static List<Group> OpptwoLibs = new List<Group>();

        /// <summary>
        /// plays the current postion to the end and counts 
        /// </summary>
        public void playout(Tree theTree)
        {
            neutrals.Clear();
            //Dictionary<int,int> themoves;
            bool bmoves = true;
            bool wmoves = true;
            do
            {
                if (mytoMove == color.black)
                {
                    int move = getPlayOutMove(theTree);
                    //if (Group.getLibertyCount_full(move, this, 2) == 2 && Group.groupLenght > 5 && getmoves(mytoMove).Count > 1)
                    //{
                    //    randmovescount++;
                    //}
                    if (move > -1)
                    {
                        place(move, mytoMove);
                        bmoves = true;
                    }
                    else
                    {
                        bmoves = false;
                        mymovehistory.Add(-1);
                    }
                }
                else
                {
                    int move = getPlayOutMove(theTree);
                    //if (Group.getLibertyCount_full(move, this, 2) == 2 && Group.groupLenght > 5 && getmoves(mytoMove).Count > 1)
                    //{
                    //    randmovescount++;
                    //}
                    if (move > -1)
                    {
                        place(move, mytoMove);
                        wmoves = true;
                    }
                    else
                    {
                        wmoves = false;
                        mymovehistory.Add(-1);
                    }
                }
                //if (mymovehistory.Count > 180 && mymovehistory.Count % 5 == 0)
                //{
                //    if (countnew(mytoMove, false) > 0)
                //    {
                //        ++randmovescount;
                //        myWinner = mytoMove;
                //    }
                //}
                changemycolortoMove();
                //writeboardandwait();
            } while ((bmoves || wmoves) && myWinner == color.empty && mymovehistory.Count < myboardsize * myboardsize * 15);
            
            countnew(mytoMove);
            
            //if (myResult == 0)
            //{
            //    countnew(mytoMove);
            //}
            //else
            //{
            //    ;
            //}
            
            //writeboardandwait();
        }

        private int getPlayOutMove(Tree theTree)
        {
            if (myEmptyFields.Count < 2)
            {
                if (myEmptyFields.Count == 0) return -1;
                int pos = myEmptyFields.Keys.FirstOrDefault();
                if (checkPositionAsMove(mytoMove, pos))
                {
                    return pos;
                }
                return -1;
            }

            //if (myEmptyFields.Count < 100 && mymovehistory.Count % 5 == 0)
            //{
            //    count(mytoMove);
            //    if (myWinner == mytoMove)
            //    {
            //        //if (myEmptyFields.Count > 100)
            //        //{
            //        //    ++randmovescount;
            //        //    ;
            //        //}
            //        ++randmovescount;
            //        return -1;
            //    }
                
            //}
            //capturesave.Clear();
            //savemoves1.Clear();
            //capturemoves1.Clear();
            //hanemoves.Clear();
            //int libs = 0;
            // play to save a group
            alsoChecked = -1;
            lastMove = -1;
           
            if (mymovehistory.Count > 0)
            {
                lastMove = mymovehistory[mymovehistory.Count - 1];
                if (lastMove > -1)
                {
                    lastGroup = myGroup[myGroupPosition[lastMove]];
                }
            }
            else
            {
                if (Tree.myMoveHistory.Count > 0)
                {
                    lastMove = Tree.myMoveHistory[Tree.myMoveHistory.Count - 1];
                    lastGroup = myGroup[myGroupPosition[lastMove]];
                }
            }
            if (mymovehistory.Count == theTree.myStartpos && theTree.patternmoves1.Count > 0
                && myRandom.Next(0, 10) < 9)
            {
                return theTree.patternmoves1.ElementAt(myRandom.Next(0, theTree.patternmoves1.Count)).Key;
            }
           
            int ret1 = getPlayOutMoveBigCapture();
            if (ret1 != -1)
            {
                return ret1;
            }

            // play neutrals
            {
                if (Tree.myMoveHistory.Count + mymovehistory.Count == 249)
                {
                    neutrals.Clear();
                }
                if (Tree.myMoveHistory.Count + mymovehistory.Count > 249 && (Tree.myMoveHistory.Count + mymovehistory.Count) % 50 == 0)
                {
                    foreach (Group cGroup in myGroup.Values)
                    {
                        foreach (Group dGroup in myGroup.Values)
                        {
                            if (cGroup.myposition != dGroup.myposition && cGroup.myEyes.Count > 1 && dGroup.myEyes.Count > 1 && cGroup.myColor != dGroup.myColor)
                            {
                                foreach (int n in cGroup.myLibs.Keys)
                                {
                                    if (dGroup.myLibs.ContainsKey(n))
                                    {
                                        neutrals[n] = n;
                                        //++randmovescount;
                                    }
                                }
                            }
                        }
                    }
                }
                if (Tree.myMoveHistory.Count + mymovehistory.Count > 249 && neutrals.Count > 0)
                {
                    int n = neutrals.ElementAt(myRandom.Next(0, neutrals.Count)).Key;
                    neutrals.Remove(n);
                    if (checkPositionAsMove(mytoMove, n))
                    {
                        return n;
                    }
                }
            }

            

            int ret = getPlayOutMoveFromLast();
            if (ret != -1)
            {
                return ret;
            }


            if (CenterOfDeadShapeMove > -1)
            {
                if (myEmptyFields.ContainsKey(CenterOfDeadShapeMove) && checkPositionAsMove(mytoMove, CenterOfDeadShapeMove) && myGroupPosition.ContainsKey(CenterOfDeadShapeMove_Killer))
                {
                    if (myGroup[myGroupPosition[CenterOfDeadShapeMove_Killer]].myEyes.Count > 0 || myGroup[myGroupPosition[CenterOfDeadShapeMove_Killer]].mypotEye.Count > 3 || myGroup[myGroupPosition[CenterOfDeadShapeMove_Killer]].myLibs.Count > 8)
                    {
                        CenterOfDeadShapeMove = -1;
                    }
                    else
                    {
                        foreach (int nei in Group.getNeighbors(CenterOfDeadShapeMove, myboardsize).Keys)
                        {
                            if (myGroupPosition.ContainsKey(nei))
                            {
                                if (myGroup[myGroupPosition[nei]].myEyes.Count > 0 || myGroup[myGroupPosition[nei]].mypotEye.Count > 0 || myGroup[myGroupPosition[nei]].myLibs.Count>8)
                                {
                                    CenterOfDeadShapeMove = -1;
                                    break;
                                }
                            }
                        }
                    }
                    if (CenterOfDeadShapeMove > -1)
                    {
                        //++randmovescount;
                        int cods = CenterOfDeadShapeMove;
                        return cods;
                    }
                    CenterOfDeadShapeMove = -1;
                }
                CenterOfDeadShapeMove = -1;
            }

            //if (thepatternmove.Count > 0)
            //{
            //        //++randmovescount;
            //        return thepatternmove.ElementAt(myRandom.Next(0, thepatternmove.Count)).Key;
            //}
            //if (mymovehistory.Count < 21 && mymovehistory.Count>2)
            //{
            //    lastMove = mymovehistory[mymovehistory.Count - 3];
            //    thepatternmove = getPlayOutPattern(lastMove);
            //    if (thepatternmove.Count > 0 )
            //    {
            //        //++randmovescount;
            //        return thepatternmove.ElementAt(myRandom.Next(0, thepatternmove.Count)).Key;
            //    }
            //}

            int theReturn = -1;
            theReturn = getTopMove(40);
            if (theReturn > -1 && (Group.getLibertyCount_full(theReturn, this, 1) > 1 || Group.groupLenght < 5))
            {
                return theReturn;
            }

            //if (mymovehistory.Count > theTree.myStartpos && mymovehistory.Count < 11)
            //{
            //    Dictionary<int, int> pl = getPlayOutPattern(lastMove);
            //    if (pl.Count > 0)
            //    {
            //        int test = pl.ElementAt(myRandom.Next(0, pl.Count)).Key;
            //        if (checkPositionAsMove(mytoMove, test))
            //        {
            //            ++randmovescount;
            //            return test;
            //        }

            //    }
            //}
            //lastGroup = null;
            //if (mymovehistory.Count > 2)
            //{
            //    lastMove = mymovehistory[mymovehistory.Count - 3];
            //    if (myGroupPosition.ContainsKey(lastMove))
            //    {
            //        lastGroup = myGroup[myGroupPosition[lastMove]];
            //    }
            //}
            //if (Tree.myMoveHistory.Count > 0)
            //{
            //    ;
            //}

            //if (lastGroup != null)
            //{
            //    ret = getPlayOutMoveFromLast();
            //}
            //if (ret != -1)
            //{
            //    return ret;
            //}
            return getRandomMove();

        }

        public Dictionary<int, int> getPlayOutPattern(int lastpos)
        {
            Dictionary<int, int> theReturn = new Dictionary<int, int>();
            //Dictionary<int, int> theQReturn = new Dictionary<int, int>();
            long key = Pattern.getpatternkey(this, lastpos, lastpos);
            if (key == 0) return theReturn;
            if (Pattern.patterns.ContainsKey(key))
            {
                foreach (long answerkey in Pattern.patterns[key].answer.Keys)
                {
                    int answerpos = (int)(answerkey / Pattern.divpos);
                    if (checkPositionAsMove(mytoMove, answerpos))
                    {
                        if (Pattern.getpatternkey(this, answerpos, answerpos) == answerkey)
                        {
                            //++randmovescount;
                            theReturn[(int)answerpos] = Pattern.patterns[key].answer[answerkey].wins * 100 / Pattern.patterns[key].answer[answerkey].vorkommen;
                            //if (myRandom.Next(Pattern.patterns[key].answer[answerkey].vorkommen) < Pattern.patterns[key].answer[answerkey].wins)
                            //{
                            //    theQReturn[(int)answerpos] = theReturn[(int)answerpos];
                            //}
                            //else
                            //{
                            //    ;
                            //}
                        }
                    }
                }
            }
            //if (theQReturn.Count>0)
            //{
            //    return theQReturn;
            //}
            //}
            return theReturn;
        }

        private int getPlayOutMoveBigCapture()
        {
            return -1;
            if (myRandom.Next(0, 12) < 6) return -1;
                
            foreach(Group cGroup in myGroup.Values)
            {
                if (cGroup.myColor == mytoMove || cGroup.myFields.Count < 4 || cGroup.myLibs.Count > 1) continue;
                int thereturn = cGroup.myLibs.FirstOrDefault().Key;
                //if (cGroup.myLibs.Count == 2 && myRandom.Next(0, 10) < 5)
                //{
                //    thereturn = cGroup.myLibs.LastOrDefault().Key;
                //    ++randmovescount;
                //}
                //if (checkPositionAsMove(mytoMove, thereturn))
                //{
                    //++randmovescount;
                    return thereturn;
                //}    

            }
            return -1;
        }

        private int getPlayOutMoveFromLast()
        {
            if (lastMove > -1)
            {
                createownAround();
                if (myRandom.Next(0, 12) < 2)
                {
                    geturgentMoves();

                    if (capturesave.Count > 0)
                    {
                        ++capturesavemovescount;
                        return capturesave.ElementAt(myRandom.Next(0, capturesave.Count)).Key;
                    }
                }

                getSaveMoves(1);

                if (capturesave.Count > 0)
                {
                    ++capturesavemovescount;
                    return capturesave.ElementAt(myRandom.Next(0, capturesave.Count)).Key;
                }
                if (savemoves1.Count > 0)
                {
                    ++savemovescount;
                    return savemoves1.ElementAt(myRandom.Next(0, savemoves1.Count)).Key;
                }

                getHaneMoves();

                if (hanemoves.Count > 0)
                {
                    ++hanemovescount;
                    return hanemoves.ElementAt(myRandom.Next(0, hanemoves.Count)).Key;
                }


            }
            getCaptureMoves(1);
            if (capturemoves1.Count > 0)
            {
                ++capturemovescount;
                return capturemoves1.ElementAt(myRandom.Next(0, capturemoves1.Count)).Key;
            }

            //int test = getTopMove(10);
            //if (test > -1) return test;

            //if (myRandom.Next(0, 10) < 3)
            //{
            //    getDoubleAtari();
            //    if (capturesave.Count > 0)
            //    {
            //        ++capturesavemovescount;
            //        ++randmovescount;
            //        return capturesave.ElementAt(myRandom.Next(0, capturesave.Count)).Key;
            //    }
            //}

            //if (myRandom.Next(0, 10) < 9)
            {
                getSaveMoves(2);
            }


            if (capturesave.Count > 0)
            {
                ++capturesavemovescount;
                return capturesave.ElementAt(myRandom.Next(0, capturesave.Count)).Key;
            }
            if (savemoves1.Count > 0)
            {
                ++savemovescount;
                return savemoves1.ElementAt(myRandom.Next(0, savemoves1.Count)).Key;
            }

            //if (myRandom.Next(0, 10) < 19)
            {
                getCaptureMoves(2);
            }
            if (capturemoves1.Count > 0)
            {
                ++capturemovescount;
                return capturemoves1.ElementAt(myRandom.Next(0, capturemoves1.Count)).Key;
            }

           

            //if (myRandom.Next(0, 10) < 19)
            {
                getSaveMoves(3);
            }

            if (capturesave.Count > 0)
            {
                ++capturesavemovescount;
                return capturesave.ElementAt(myRandom.Next(0, capturesave.Count)).Key;
            }
            if (savemoves1.Count > 0)
            {
                ++savemovescount;
                return savemoves1.ElementAt(myRandom.Next(0, savemoves1.Count)).Key;
            }

            //if (myRandom.Next(0, 10) < 19)
            {
                getCaptureMoves(3);
                if (capturemoves1.Count > 0)
                {
                    ++capturemovescount;
                    return capturemoves1.ElementAt(myRandom.Next(0, capturemoves1.Count)).Key;
                }
            }

            getConnectMoves();
            if (savemoves1.Count > 0)
            {
                ++savemovescount;
                //++randmovescount;
                return savemoves1.ElementAt(myRandom.Next(0, savemoves1.Count)).Key;
            }

            

            //getsavecut_own();
            //if (savemoves1.Count > 0)
            //{
            //    ++savemovescount;
            //    ++randmovescount;
            //    return savemoves1.ElementAt(myRandom.Next(0, savemoves1.Count)).Key;
            //}


            //if (myRandom.Next(0, 10) < 2)
            //{
            //    foreach (Group cGroup in myGroup.Values)
            //    {
            //        if (cGroup.myColor != mytoMove && cGroup.myFields.Count > 1 && cGroup.myLibs.Count < 4 && cGroup.myEyes.Count < 2)
            //        {
            //            foreach (int pos in cGroup.myLibs.Keys)
            //            {
            //                foreach (Group dGroup in myGroup.Values)
            //                {
            //                    if (dGroup.myColor == mytoMove && dGroup.myLibs.ContainsKey(pos) && (dGroup.myEyes.Count > 1 || dGroup.myLibs.Count > cGroup.myLibs.Count))
            //                    {
            //                        capturemoves1[pos] = pos;
            //                    }
            //                }
            //            }
            //        }
            //    }
            //    if (capturemoves1.Count > 0)
            //    {
            //        randmovescount++;
            //        return capturemoves1.ElementAt(myRandom.Next(0, capturemoves1.Count)).Key;
            //    }
            //}
            //if (myRandom.Next(0, 10) < 5)
            //{
            //    getSaveMoves(4);
            //}

            //if (capturesave.Count > 0)
            //{
            //    ++capturesavemovescount;
            //    return capturesave.ElementAt(myRandom.Next(0, capturesave.Count)).Key;
            //}
            //if (savemoves1.Count > 0)
            //{
            //    ++savemovescount;
            //    return savemoves1.ElementAt(myRandom.Next(0, savemoves1.Count)).Key;
            //}

            
            return -1;
        }

        private void getsavecut()
        {
            savemoves1.Clear();
            int maxlib = 3;
            // savecut
            List<int> done = new List<int>();
            foreach (int nei in lastGroup.myNeighbors.Keys)
            {
                if (myGroupPosition.ContainsKey(nei))
                {
                    if (done.Contains(myGroupPosition[nei])) continue;
                    done.Add(myGroupPosition[nei]);
                    if (myGroup[myGroupPosition[nei]].myLibs.Count < 4) continue;
                    foreach (int l in myGroup[myGroupPosition[nei]].myLibs.Keys)
                    {
                        foreach (int nei1 in Group.getNeighbors(l, myboardsize).Keys)
                        {
                            if (myGroupPosition.ContainsKey(nei1) && myGroup[myGroupPosition[nei1]].myColor != mytoMove && myGroupPosition[nei1] != lastGroup.myposition)
                            {
                                
                                    savemoves1[l] = Group.getLibertyCount_full(l, this, maxlib);
                                    if (savemoves1[l] > maxlib)
                                    {
                                        maxlib = savemoves1[l];
                                    }
                            }
                        }
                    }
                }
            }
            filterMaxLiberties(savemoves1, maxlib);
        }

        private void getConnectMoves()
        {
            List<int> own = new List<int>();
            List<int> empty = new List<int>();
            List<int> ownnei = new List<int>();
            foreach (int nei in Group.getNeighbors(lastMove, myboardsize).Keys)
            {
                if (!myGroupPosition.ContainsKey(nei))
                {
                    empty.Add(nei);
                }
                else
                {
                    if (myGroupPosition[nei] != lastGroup.myposition)
                    {
                        ownnei.Add(nei);
                        if (own.Count == 0 || !own.Contains(myGroupPosition[nei]))
                        {
                            own.Add(myGroupPosition[nei]);

                        }
                    }
                }
            }
            if (ownnei.Count == 2 && empty.Count > 0)
            {
                foreach (int lib in empty)
                {
                    if (getdistance_int(lib,ownnei[0]) < 3 &&  getdistance_int(lib,ownnei[1]) < 3 && Group.getLibertyCount_full(lib, this, 2) > 2)
                    {
                        savemoves1[lib] = lib;
                    }
                }
            }
            if (own.Count == 2 && empty.Count > 0)
            {
                foreach (int lib in empty)
                {
                    if (myGroup[own[1]].myLibs.ContainsKey(lib) && myGroup[own[0]].myLibs.ContainsKey(lib))
                    {
                        if (checkPositionAsMove(mytoMove, lib) && Group.getLibertyCount_full(lib, this, 1) > 1)
                        {
                            //++randmovescount;
                            savemoves1[lib] = lib;
                            //if (Group.getLibertyCount_full(lib, this, 2) == 2)
                            //{
                            //    ;
                            //}
                        }
                    }
                }
                if (savemoves1.Count == 0)
                {
                    foreach (int lib in myGroup[own[1]].myLibs.Keys)
                    {
                        if (myGroup[own[0]].myLibs.ContainsKey(lib))
                        {
                            if (myEmptyFields.ContainsKey(lib) && checkPositionAsMove(mytoMove, lib) && Group.getLibertyCount_full(lib, this, 1) > 1)
                            {
                                //++randmovescount;
                                savemoves1[lib] = lib;
                            }
                        }
                    }
                }
                if (savemoves1.Count == 0)
                {
                    foreach (int lib in empty)
                    {
                        foreach (int nei in Group.getNeighbors(lib, myboardsize).Keys)
                        {
                            if ((myGroup[own[1]].myLibs.ContainsKey(nei) || myGroup[own[1]].myLibs.ContainsKey(lib))
                                && (myGroup[own[0]].myLibs.ContainsKey(nei) || myGroup[own[0]].myLibs.ContainsKey(lib))
                                )
                            {
                                if (myEmptyFields.ContainsKey(lib) && checkPositionAsMove(mytoMove, lib) && Group.getLibertyCount_full(lib, this, 1) > 1)
                                {
                                    savemoves1[lib] = lib;
                                    //++randmovescount;
                                }
                            }
                        }
                    }
                }
            }
            if (savemoves1.Count == 0 && own.Count == 1 && empty.Count > 0)
            {
                foreach (int lib in empty)
                {
                    foreach (int nei in Group.getNeighbors(lib, myboardsize).Keys)
                    {
                        if (myGroupPosition.ContainsKey(nei) 
                            && myGroupPosition[nei] != own[0] 
                            && myGroup[myGroupPosition[nei]].myColor == mytoMove
                            )
                        {
                            // check direct connect
                            foreach (int c in myGroup[own[0]].myLibs.Keys)
                            {
                                //if (getdistance(c, empty > 1.5)) continue;
                                if (myGroup[myGroupPosition[nei]].myLibs.ContainsKey(c))
                                {
                                    if (myEmptyFields.ContainsKey(c) && checkPositionAsMove(mytoMove, c) && Group.getLibertyCount_full(c, this, 1) > 1)
                                    {
                                        savemoves1[c] = c;
                                        //++randmovescount;
                                    }
                                }
                                // normal connect via two libs
                                int zahl = 0;
                                foreach(int z in Group.getNeighbors(c, myboardsize).Keys)
                                {
                                    if (myGroup[myGroupPosition[nei]].myLibs.ContainsKey(z)) ++zahl;
                                }
                                if (zahl > 1)
                                {
                                    if (myEmptyFields.ContainsKey(c) && checkPositionAsMove(mytoMove, c) && Group.getLibertyCount_full(c, this, 1) > 1)
                                    {
                                        savemoves1[c] = c;
                                        //++randmovescount;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (savemoves1.Count == 0 && own.Count == 1 && empty.Count > 0)
            {
                foreach (int lib in empty)
                {
                    foreach (int nei in Group.getNeighbors(lib, myboardsize).Keys)
                    {
                        if (myGroupPosition.ContainsKey(nei)
                            && myGroupPosition[nei] != own[0]
                            && myGroup[myGroupPosition[nei]].myColor == mytoMove
                            )
                        {
                            if (checkPositionAsMove(mytoMove, lib) && Group.getLibertyCount_full(lib, this, 1) > 1)
                            {
                                foreach (int f in myGroup[own[0]].myFields.Keys)
                                {
                                    if (getdistance_int(f, nei) < 9 && getdistance_int(f, lib) < 3)
                                    {
                                        savemoves1[lib] = lib;
                                        //++randmovescount;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

        }
        private int getTopMove(int prob)
        {
            if (Tree.myTopMoves.Count > 0 && myRandom.Next(0, 100) < prob)
            {

                int pos = Tree.myTopMoves[myRandom.Next(0, Tree.myTopMoves.Count)];
                if (myEmptyFields.ContainsKey(pos) && checkPositionAsMove(mytoMove, pos))
                {
                    //++randmovescount;
                    return pos;
                }
            }
            return -1;
        }
        private int getRandomMove()
        {
            // one try to take one of topmoves

            int theReturn = -1;
            //double themaxvalue = -1;
            //int tryout = 0;
            theList = myEmptyFields.Keys.ToList();
            //theList.AddRange(myEmptyFields.Keys);

            int selfatari = 0;
            int maxtryself = 5;
            if (theList.Count < maxtryself) maxtryself = theList.Count;
            //if (Tree.myRootBoard.mytoMove == color.white) maxtryself = 4;
            while (theList.Count > 0)
            {
                int pos = theList[myRandom.Next(0, theList.Count)];
                if (checkPositionAsMove(mytoMove, pos)
                        && !ispotentialeye(pos)
                    //&& (Group.getLibertyCount_full(pos, this, 1) > 1 || Group.groupLenght < 6)
                    && !sekiLibs.ContainsKey(pos)
                    //&& (theList.Count < myboardsize * myboardsize * 3 / 4 || Group.getLibertyCount(pos, this) > 3)
                    //&& !ispotentialeye(pos) && !isSekiLib(pos)
                    )
                //&& !sekiLibs.ContainsKey(pos))
                {
                    //if (mymovehistory.Count <= myboardsize * myboardsize / 4 && Group.getLibertyCount_full(pos, this, 2) <= 2)
                    //{
                    //    ++randmovescount;
                    //}
                    //Tree.myRootBoard.mytoMove == color.black ||
                    if (selfatari > maxtryself || 
                        //!isSelfAtatri(pos)
                        //(theList.Count < myboardsize * myboardsize * 3 / 4 || Group.getLibertyCount(pos, this) > 3)
                        //&& (!sekiLibs.ContainsKey(pos))
                        //                        && (!isfirstline(pos) || Tree.myMoveHistory.Count > myboardsize * myboardsize / 3)
                        (!isfirstline(pos) || Tree.myMoveHistory.Count + mymovehistory.Count > myboardsize * myboardsize / 4)
                        //&& (selfatari>0  || Tree.myMoveHistory.Count + mymovehistory.Count > myboardsize * myboardsize / 2 || !isEmptyTriangle(pos) )
                        //&& (!isOverconcentrated(pos))
                        //&& (mymovehistory.Count > myboardsize * myboardsize / 2 || selfatari > 1 || Group.getLibertyCount_full(pos, this, 2) > 2)
                        //&& (Tree.myMoveHistory.Count + mymovehistory.Count > myboardsize * myboardsize / 5 || Group.getLibertyCount(pos, this) == 4)
                        //&& !sekiLibs.ContainsKey(pos)
                        //&& (Group.getLibertyCount_full(pos, this, 1) > 1  || Group.groupLenght < 5)
                        //&& !Tree.myBadMoves.Contains(pos)
                        //&& (!issecondline(pos) || isgoodsecondline(pos))
                        //&&!isSekiLib(pos)
                        //&& (!isNearDeadGroup(pos) || Tree.myRootBoard.mytoMove == color.black)
                        )
                    {
                       
                        if (selfatari > maxtryself)
                        {
                            //randmovescount++;
                        }
                        else
                        {
                            noselfatarirandmovescount++;
                        }
                        //if (Group.getLibertyCount_full(pos, this, 1) == 1 && Group.groupLenght > 2)
                        //{
                        //    randmovescount++;
                        //}
                        //++tryout;
                        //if (Tree.TreeRoot.mychildRaveVorkommen.ContainsKey(pos))
                        //{
                        //    if ((Tree.TreeRoot.mychildRaveGewonnen[pos]+0.5)/(Tree.TreeRoot.mychildRaveVorkommen[pos]+1) > themaxvalue)
                        //    {
                        //        themaxvalue = (Tree.TreeRoot.mychildRaveGewonnen[pos] + 0.5) / (Tree.TreeRoot.mychildRaveVorkommen[pos] + 1);
                        //        theReturn = pos;
                        //    }
                        //}
                        //if (tryout>3 || tryout> theList.Count)
                        theReturn = pos;
                        break;
                        //}
                        ++selfatari;
                    }
                    else
                    {
                        ++selfatari;

                    }
                }
                else
                {
                    theList.Remove(pos);
                }
            }
            return theReturn;
        }

        private void createownAround()
        {
            ownAroundLastGroup.Clear();
            //if (lastGroup.myFields.Count == 1 && lastGroup.myLibs.Count == 4) return;
            //foreach(int nei in lastGroup.myNeighbors.Keys)
            foreach(int nei in Group.getNeighbors(lastMove,myboardsize).Keys)
            {
                if (!myGroupPosition.ContainsKey(nei)) continue;
                //if (lastGroup.myLibs.ContainsKey(nei)) continue;
                int libs =myGroup[myGroupPosition[nei]].myLibs.Count;
                if (libs < 4 && myGroup[myGroupPosition[nei]].myColor == mytoMove)
                //&& myGroup[myGroupPosition[nei]].myEyes.Count < 2)
                {
                    if (!ownAroundLastGroup.ContainsKey(libs))
                    {
                        ownAroundLastGroup[libs] = new List<int>();
                    }
                    if (!ownAroundLastGroup[libs].Contains(myGroupPosition[nei]))
                    {
                            ownAroundLastGroup[libs].Add(myGroupPosition[nei]);
                    }
                }
            }
        }


        // return all moves around last groups neibourgh groups 
        private void geturgentMoves()
        {
            capturesave.Clear();
            int maxLib = 0;
            foreach(List<int> theList in ownAroundLastGroup.Values)
            {
                foreach (int g in theList)
                {

                    //    }
                    //}
                    ////foreach(int nei in Group.getNeighbors(lastMove,myboardsize).Keys)
                    //foreach (int nei in lastGroup.myNeighbors.Keys)
                    //{
                    //    if (lastGroup.myLibs.ContainsKey(nei)) continue;
                    //    if (doneGroups.Contains(myGroupPosition[nei])) continue;
                    //    doneGroups.Add(myGroupPosition[nei]);
                    //    //                if (myGroupPosition.ContainsKey(nei))
                    //    //                {

                    //    //if (myGroup[myGroupPosition[nei]].myFields.Count>0)
                    //    //{
                    Group cGroup = myGroup[myGroupPosition[g]];
                    if (cGroup.myLibs.Count <= 3 && cGroup.myEyes.Count < 2)
                    {
                        if (cGroup.myLibs.Count < lastGroup.myLibs.Count || lastGroup.myEyes.Count > 1)
                        {
                            // check sourrounding groups
                            foreach (int nei1 in cGroup.myNeighbors.Keys)
                            {
                                if (cGroup.myLibs.ContainsKey(nei1)) continue;
                                if (myGroupPosition[nei1] == lastGroup.myposition) continue;
                                Group oGroup = myGroup[myGroupPosition[nei1]];
                                if (oGroup.myLibs.Count <= cGroup.myLibs.Count && oGroup.myEyes.Count < 2)
                                {
                                    foreach (int nei2 in oGroup.myLibs.Keys)
                                    {
                                        int lib2 = Group.getLibertyCount_full(nei2, this, oGroup.myLibs.Count - 1);
                                        if (lib2 >= maxLib && lib2 > oGroup.myLibs.Count - 1)
                                        {
                                            if (Group.getLibertyCount_full(nei2, this, 1) > 1)
                                            {
                                                maxLib = lib2;

                                                if (capturesave.ContainsKey(nei2))
                                                {
                                                    capturesave[nei2] += lib2;
                                                }
                                                else
                                                {
                                                    //++randmovescount;
                                                    capturesave[nei2] = lib2;

                                                }
                                            }
                                        }
                                    }
                                    //capturesave.AddRange(myGroup[myGroupPosition[nei1]].myLibs.Keys);
                                }
                            }
                        }
                        //}
                    }
                }
            }
 //           }
            if (capturesave.Count > 1)
            {
                foreach (int pos in capturesave.Keys.ToList())
                {
                    if (capturesave[pos] > maxLib)
                    {
                        maxLib = capturesave[pos];
                    }
                }
                filterMaxLiberties(capturesave, maxLib);
            }
        }


        private void getCaptureMoves(int libs)
        {
            capturemoves1.Clear();
            if (lastMove < 0) return;
            int maxlib = 0;
            if (lastGroup.myLibs.Count == libs && lastGroup.myEyes.Count < 2)
            {
                //List<int> minLibGroup = new List<int>();
                //foreach(int nei in lastGroup.myNeighbors.Keys)
                //{
                //    if (myGroupPosition.ContainsKey(nei) && myGroup[myGroupPosition[nei]].myLibs.Count < libs)
                //    {
                //       if (!minLibGroup.Contains(myGroupPosition[nei]))
                //       {
                //           minLibGroup.Add(myGroupPosition[nei]);
                //       }
                //    }
                //}
                
                bool isladder = false;
                if (libs == 2 && checkladder() == true) isladder = true;
                foreach (int capturemove in lastGroup.myLibs.Keys)
                {
                    if (Group.getLibertyCount_full(capturemove, this, 1) == 1) continue;
                        //bool docont = false;
                        //foreach (int own in minLibGroup)
                        //{
                        //    if (!myGroup[own].myLibs.ContainsKey(capturemove))
                        //    {
                        //        docont = true;
                        //        break;

                        //    }
                        //}
                        //if (docont) continue;
                    if (lastGroup.myFields.Count > 0 || isladder)
                    {
                        
                        int lib2 = Group.getLibertyCount_full(capturemove, this, libs - 1);
                        if (lib2 >= maxlib && (lib2 > libs - 1 || lastGroup.myLibs.Count == 1))
                        {
                            if (checkPositionAsMove(mytoMove, capturemove))
                            {
                                capturemoves1[capturemove] = lib2;
                                if (libs == 2 && isladder)
                                {
                                    
                                    //++randmovescount;
                                    capturemoves1[capturemove] = Group.getLibertyCount(capturemove, this);
                                }
                                else
                                {
                                    maxlib = lib2;
                                }
                            }
                        }
                    }
                }
                //if (minLibGroup.Count>1 && capturemoves1.Count>0)
                //{
                //    ;
                //}
            }

            if ( 1== 2 && libs < 4 && capturemoves1.Count == 0
                 && myRandom.Next(0, 10) < 1
                 )
            {
                int maxgroup = 0;
                foreach (Group cGroup in myGroup.Values)
                {

                    if (cGroup.myColor != mytoMove && cGroup.myEyes.Count < 2 && cGroup.myFields.Count > 1 && cGroup.getLibertyCount(this) == libs)
                    //&& cGroup.alive < cGroup.dead*2)
                    {
                        bool docont = false;
                        foreach (int nei in cGroup.myNeighbors.Keys)
                        {
                            if (cGroup.myLibs.ContainsKey(nei)) continue;
                            if (myGroup[myGroupPosition[nei]].myLibs.Count<libs) 
                            {
                                docont = true;
                                break;
                            }
                        }
                        if (docont) continue;
                        foreach (int nei in (cGroup.myLibs.Keys))
                        {
                            int lib2 = Group.getLibertyCount_full(nei, this, libs - 1);
                            if (checkPositionAsMove(mytoMove, nei) && (cGroup.myFields.Count > 0 && lib2 > libs - 1))
                            {
                                if (cGroup.myFields.Count >= maxgroup)
                                {
                                    if (cGroup.myFields.Count > maxgroup)
                                    {
                                        capturemoves1.Clear();
                                    }
                                    if (lib2 >= maxlib)
                                    {
                                        maxlib = lib2;
                                        capturemoves1[nei] = lib2;
                                    }
                                    maxgroup = cGroup.myFields.Count;
                                }
                            }
                        }
                    }
                }
                if (capturemoves1.Count > 0 && libs > 1)
                {
                    //++randmovescount;
                    ;
                }
                return;
            }
            //if (libs > 1 && capturemoves1.Count > 0) ++randmovescount;
            filterMaxLiberties(capturemoves1, maxlib);
        }

        private bool checkladder()
        {
            if (getx(lastMove) < 3 || gety(lastMove) < 3) return false;
            int f2;
            int f1 = lastGroup.myLibs.FirstOrDefault().Key;
            int lib1 = Group.getLibertyCount(f1, this);
            if (lib1 == 3)
            {
                f2 = lastGroup.myLibs.FirstOrDefault().Key;
                f1 = lastGroup.myLibs.ElementAt(1).Key;
                if (Group.getLibertyCount(f1, this) != 2) return false;
            }
            else
            {
                f2 = lastGroup.myLibs.ElementAt(1).Key;
                if (lib1 != 2 || Group.getLibertyCount(f2, this) != 3) return false;
            }
            // f1 has the 3 libs
            int diff = f1 + f2 - 2 * lastMove;
            if (diff == 0) return false;
            if (Group.getLibertyCount(lastMove, this) != 2) return false;
            // direct ladderbreaker
            List<int> breaker = new List<int>();
            breaker.Add(f2);
            breaker.Add(f1);
            breaker.Add(lastMove + 2*(f1-lastMove));
            breaker.Add(lastMove + diff);
            int distance = 1;
            while (getx(lastMove + distance * diff) > 1 && gety(lastMove + distance * diff) > 1)
            {
                foreach(int ladderbreaker in breaker)
                {
                    if (myGroupPosition.ContainsKey(ladderbreaker + distance * diff))
                    {
                        if (myGroup[myGroupPosition[ladderbreaker + distance * diff]].myLibs.Count > 2)
                        {
                            if (myGroup[myGroupPosition[ladderbreaker + distance * diff]].myColor == mytoMove)
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                    }
                }
                ++distance;
            }
            return true;
        }

        private void getHaneMoves()
        {
            hanemoves.Clear();
            // play to hane or cut
            if (lastMove < 0) return;
            //foreach(int newpos in lastGroup.myLibs.Keys)
            //{
            //    if (Group.getLibertyCount(newpos, this) == 3)
            //    {
            //        if (getdistance_int(newpos, lastMove) == 1)
            //        {
            //            foreach(int nei in lastGroup.myNeighbors.Keys)
            //            {
            //                if (myGroupPosition.ContainsKey(nei) && getdistance_int(newpos, nei) == 2)
            //                {
            //                    if (checkPositionAsMove(mytoMove,newpos))
            //                    {
            //                        hanemoves[newpos] = newpos;
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}
            if (hanemoves.Count > 0) return;
            if (lastGroup.myLibs.Count > 4) return;
            int libs = lastGroup.getLibertyCount(this);
            int maxlib = libs-1;

            if (libs > 1)
            {
                int own = -1;
            //    // simple ladder
            //    if (lastGroup.myLibs.Count == 2)
            //    {
            //        foreach (int pos in lastGroup.myLibs.Keys)
            //        {
            //            if (Group.getLibertyCount(pos, this) == 3)
            //            {
            //                if (!hanemoves.Contains(pos))
            //                {
            //                    hanemoves.Add(pos);
            //                }
            //                ++randmovescount;
            //                //return;
            //            }
            //        }
            //    }
            //    return;

                // attach or shoulderhit
                if (lastGroup.myFields.Count == 1 && (lastGroup.myLibs.Count >= 3 || getx(lastGroup.myposition) == 0 || gety(lastGroup.myposition) == 0))
                {
                     
                    Dictionary<int, int> therad1 = Group.getNeighbors_rad_no_cache(lastGroup.myposition, this, 1);
                    if (therad1.Count == 1)
                    {
                        Group cGroup = myGroup[therad1.FirstOrDefault().Value];
                        if (cGroup.myColor == mytoMove && cGroup.myEyes.Count < 2
                            && cGroup.myLibs.Count > 1)
                        {
                            foreach (int pos in Group.getNeighbors_Fields_rad(lastGroup.myposition, this, 1).Keys)
                            {
                                if (cGroup.myNeighbors.ContainsKey(pos) || lastGroup.myLibs.ContainsKey(pos))
                                {
                                    if (checkPositionAsMove(mytoMove, pos))
                                    {
                                        bool doit = true;
                                        own = therad1.Keys.FirstOrDefault();
                                        foreach (int nei in Group.getNeighbors(pos, myboardsize).Keys)
                                        {
                                            if (cGroup.myLibs.ContainsKey(nei))
                                            {
                                                doit = false;
                                                break;
                                            }
                                        }
                                        if ((doit && cGroup.myLibs.ContainsKey(pos))
                                            || (!doit && !cGroup.myLibs.ContainsKey(pos))
                                            )
                                        {
                                            int lib2 = Group.getLibertyCount_full(pos, this, libs-1);
                                            if (lib2 >= maxlib && lib2 > 1)
                                            {
                                                if (((getx(lastMove) == 2 && gety(lastMove) >= 2 && gety(lastMove) < 4) || (gety(lastMove) == 2 && getx(lastMove) >= 2 && getx(lastMove) < 4)) 
                                                    && cGroup.myNeighbors.ContainsKey(lastMove)
                                                )
                                                {
                                                    if (cGroup.myFields.Count==1 && (getx(cGroup.myposition) == 2 || gety(cGroup.myposition) == 2))
                                                    {
                                                        if (
                                                            (gety(lastMove) == 2 && gety(pos) == 1 && getx(lastMove) == getx(pos))
                                                            ||
                                                            (getx(lastMove) == 2 && getx(pos) == 1 && gety(lastMove) == gety(pos))
                                                            )
                                                        {
                                                            hanemoves.Clear();
                                                            hanemoves[pos] = lib2;
                                                            break;
                                                        }
                                                    }
                                                }
                                                maxlib = lib2;
                                                hanemoves[pos] = lib2;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (therad1.Count == 2)
                    {
                        // connect or cut
                        Group cGroup = myGroup[therad1.FirstOrDefault().Value];
                        Group dGroup;
                        if (cGroup.myColor != mytoMove)
                        {
                            cGroup = myGroup[therad1.ElementAt(1).Value];
                            dGroup = myGroup[therad1.FirstOrDefault().Value];
                        }
                        else
                        {
                            dGroup = myGroup[therad1.ElementAt(1).Value];
                        }
                        if (cGroup.myposition != dGroup.myposition && (cGroup.myColor == mytoMove || dGroup.myColor == mytoMove ))
                        {
                            foreach(int nei in cGroup.myLibs.Keys)
                            {
                                if (Group.getLibertyCount_full(nei, this, 1) == 1) continue;
                                if (dGroup.myLibs.ContainsKey(nei)||lastGroup.myLibs.ContainsKey(nei))
                                {
                                    if (myEmptyFields.ContainsKey(nei) && checkPositionAsMove(mytoMove, nei))
                                    {
                                        //randmovescount++;
                                        hanemoves.Add(nei, Group.getLibertyCount_full(nei, this, maxlib));
                                    }
                                }
                            }
                        }
                    }

                }
                if (hanemoves.Count == 0 && lastGroup.myLibs.Count < 5)
                {
                    List<int> ownGroups = new List<int>();
                    List<int> possible = new List<int>();
                    foreach (int pos in lastGroup.myNeighbors.Keys)
                    //foreach (int pos in Group.getNeighbors(lastMove, myboardsize).Keys)
                    {
                        if (!myGroupPosition.ContainsKey(pos))
                        {
                            if (myEmptyFields.ContainsKey(pos))
                            possible.Add(pos);
                        }
                        else
                        {
                            Group posGroup = myGroup[myGroupPosition[pos]];
                            if (posGroup.myColor == mytoMove
                                && posGroup.myEyes.Count < 2
                                && posGroup.myLibs.Count > 1)
                            {
                                if (!ownGroups.Contains(posGroup.myposition))
                                {
                                    ownGroups.Add(myGroupPosition[pos]);
                                }
                                own = pos;
                            }
                        }
                    }
                    if (possible.Count > 0 && ownGroups.Count>0)
                    {
                        bool isshrtliberty = false;
                        foreach (int ownG in ownGroups)
                        {
                            //if (myGroup[ownG].myLibs.Count <= lastGroup.myLibs.Count - 1)
                            //{
                            //    return;
                            //}

                            if (myGroup[ownG].myLibs.Count <= lastGroup.myLibs.Count-1)
                            {
                                isshrtliberty = true;
                                foreach (int nei in myGroup[ownG].myLibs.Keys)
                                {
                                    int lib2 = Group.getLibertyCount_full(nei, this, lastGroup.myLibs.Count + 1);
                                    if (lib2 >= lastGroup.myLibs.Count + 1)
                                    {
                                        bool ok = false;
                                        if (Group.getLibertyCount(nei, this) == 1)
                                        {
                                            foreach(int nei1 in Group.getNeighbors(nei, myboardsize).Keys)
                                            {
                                                if (myGroupPosition.ContainsKey(nei1))
                                                {
                                                    if (myGroup[myGroupPosition[nei1]].myColor != mytoMove)
                                                    {
                                                        ok = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        if (ok == true)
                                        {
                                            maxlib = lib2;
                                            hanemoves[nei] = lib2;
                                            //++randmovescount;
                                        }
                                    }
                                }
                                // dead group?
                                
                            }
                            
                        }
                        if (hanemoves.Count == 0 && isshrtliberty)
                        {
                            return;
                        }
                        if (maxlib < lastGroup.myLibs.Count - 1) maxlib = lastGroup.myLibs.Count - 1;
                        foreach (int pos in possible)
                        {
                            if (Math.Abs(pos - own) == 2 || Math.Abs(pos - own) == 2 * myboardsize) continue;
                            if (!checkPositionAsMove(mytoMove, pos)) continue;
                            int lib2 = Group.getLibertyCount_full(pos, this, maxlib);
                            if (lib2 <= lastGroup.myLibs.Count - 1 || lib2 < maxlib) continue;
                            //if (checkPositionAsMove(mytoMove, pos))
                            //{
                                //if (lib2 <= lastGroup.myLibs.Count - 1)
                                //    foreach (int n in Group.getNeighbors(pos, myboardsize).Keys)
                                //    {
                                //        if (!myGroupPosition.ContainsKey(n)) ++lib2;
                                //    }
                                //if (lib2 > 2 || lib2 > 1 && myGroup[myGroupPosition[own]].myLibs.Count > 2)
                                //{
                                maxlib = lib2;
                                hanemoves[pos] =  lib2;
                                //}
                            //}
                        }
                    }
                }
            }
            filterMaxLiberties(hanemoves, maxlib);
        }

        private void filterMaxLiberties(Dictionary<int, int> theList, int maxlib)
        {
            if (theList.Count > 1)
            {
                foreach (int pos in theList.Keys.ToList())
                {
                    if (theList[pos] < maxlib)
                    {
                        theList.Remove(pos);
                        //++randmovescount;
                    }
                }
            }
        }

        private void getSaveMoves(int reqlibs)
        {
            if (lastMove < 0) return;
            savemoves1.Clear();
            capturesave.Clear();
            int maxlib = 0;
            //List<int> doneGroups = new List<int>();
            if (!ownAroundLastGroup.ContainsKey(reqlibs)) return;
            //if (reqlibs == 2 && lastGroup.myLibs.Count > reqlibs)
            //{

            //    foreach (int pos1 in lastGroup.myNeighbors.Keys)
            //    {
            //        if (myGroupPosition.ContainsKey(pos1))
            //        {
            //            if (doneGroups.Contains(myGroupPosition[pos1])) continue;
            //            foreach (int pos in ownAroundLastGroup[reqlibs])
            //            //    foreach (int pos in Group.getNeighbors(lastMove, myboardsize).Keys)
            //            {
            //                if (myGroupPosition[pos1] == pos) continue;
            //                Group cGroup = myGroup[myGroupPosition[pos]];
            //                if (cGroup.myEyes.Count > 1) continue;

            //                //if (myGroupPosition.ContainsKey(pos))
            //                //{
            //                Group dGroup = myGroup[myGroupPosition[pos1]];
            //                foreach (int nei in cGroup.myLibs.Keys)
            //                {
            //                    if (dGroup.myLibs.ContainsKey(nei))
            //                    {
            //                        int lib1 = Group.getLibertyCount_full(nei, this, reqlibs);
            //                        if (lib1 > reqlibs && Group.getLibertyCount(nei, this) == 2)
            //                        {
            //                            //if (checkPositionAsMove(mytoMove, nei))
            //                            //{
            //                            capturesave[nei] = lib1;
            //                            //++randmovescount;
            //                            //}
            //                        }
            //                    }
            //                }
            //            }
            //        }
            //    }
            //    if (capturesave.Count > 0)
            //    {
            //        return;
            //    }
            //}
            foreach (int pos in ownAroundLastGroup[reqlibs])
            //    foreach (int pos in Group.getNeighbors(lastMove, myboardsize).Keys)
            {
                //if (myGroupPosition.ContainsKey(pos))
                //{
                    Group cGroup = myGroup[myGroupPosition[pos]];
                    //if ((cGroup.myFields.Count == 1 && myRandom.Next(0, 10) < 4) || cGroup.myEyes.Count > 1) continue;
               

                    if (cGroup.myLibs.Count == reqlibs )
                    {
                        //if (cGroup.myFields.Count > 1 || reqlibs == 1 || myRandom.Next(0, 10) < 5)
                        //{
                            savemoveForGroupWithLibs(cGroup, reqlibs, reqlibs, maxlib);
                        //}
                    }
                //}
            }
            //if (reqlibs < 3 && capturesave.Count == 0 && savemoves1.Count == 0 && myRandom.Next(0, 18) < 1)
            //{
            //    foreach (Group cGroup in myGroup.Values)
            //    {
            //        if (cGroup.myLibs.Count == reqlibs && cGroup.myColor == mytoMove)
            //        {
            //            if (myRandom.Next(0, 3) < 1)
            //            {
            //                savemoveForGroupWithLibs(cGroup, reqlibs, reqlibs);
            //            }
            //        }
            //    }
            //}

            
            filterMaxLiberties(capturesave, maxlib);
            if (capturesave.Count > 0) return;
            filterMaxLiberties(savemoves1, maxlib);
        }
        private void savemoveForGroupWithLibs(Group cGroup, int libs, int howmany, int maxlib)
        {
            //if (libs == howmany)
            //{
                if (cGroup.myEyes.Count > 1) return;


                foreach (int nei in cGroup.myNeighbors.Keys)
                {
                    if (cGroup.myLibs.ContainsKey(nei)) continue;
                    //if (myGroupPosition.ContainsKey(nei))
                    //{
                    Group dGroup = myGroup[myGroupPosition[nei]];
                    if (dGroup.myLibs.Count <= cGroup.myLibs.Count)
                    {
                        //if (dGroup.myEyes.Count > 1)
                        //{
                        //    ;
                        //}
                        foreach (int capt in dGroup.myLibs.Keys)
                        {
                            int lib2 = Group.getLibertyCount_full(capt, this, dGroup.myLibs.Count - 1);
                            if (lib2 >= maxlib && lib2 > dGroup.myLibs.Count - 1 && checkPositionAsMove(mytoMove, capt))
                            {
                                if (Group.getLibertyCount_full(capt, this, 1) > 1)
                                {

                                    //if (libs > 2)
                                    //{
                                    //    ;
                                    //}
                                    maxlib = lib2;
                                    capturesave[capt] = lib2;
                                    //return;
                                }
                            }
                        }
                    }
                    //}
                }
                if (capturesave.Count > 0) return;

                foreach (int savemove in cGroup.myLibs.Keys)
                {
                    //if (myEmptyFields.Count>myboardsize*myboardsize*3/4 && isfirstline(savemove))
                    //{
                    //    continue;
                    //}
                    if (checkPositionAsMove(mytoMove, savemove))
                    {
                        //if (Tree.myRootBoard.mytoMove == color.white)
                        //{
                        int lib2 = Group.getLibertyCount_full(savemove, this, howmany + 1);
                        if (lib2 >= maxlib && lib2 > howmany + 1)
                        //if (lib2 >= maxlib && lib2 > howmany + 1 && getdistance(lastMove, savemove) < 2)
                        {
                            maxlib = lib2;
                            savemoves1[savemove] = lib2;
                        }
                        else
                        {
                            if (lib2 == 1)
                            {
                                foreach(int nei in Group.getNeighbors(savemove, myboardsize).Keys)
                                {
                                    if (myGroupPosition.ContainsKey(nei))
                                    {
                                        if (myGroup[myGroupPosition[nei]].myColor == mytoMove && myGroup[myGroupPosition[nei]].myposition != cGroup.myposition)
                                        {
                                            foreach (int nei1 in myGroup[myGroupPosition[nei]].myLibs.Keys)
                                            {
                                                if (Group.getLibertyCount_full(nei1, this, 2) > 2)
                                                {
                                                    if (checkPositionAsMove(mytoMove, nei1))
                                                    {
                                                        savemoves1[nei1] = Group.getLibertyCount_full(nei1, this, 2);
                                                        //++randmovescount;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            //}
        }

        public bool isfirstline(int pos)
        {
            int x = myboardsize / 2 - Math.Abs(pos % myboardsize - (myboardsize / 2));
            int y = myboardsize / 2 - Math.Abs(pos / myboardsize - (myboardsize / 2));
            if (x == 0 || y == 0)
            {
                return true;
            }
            return false;
        }
        private bool issecondline(int pos)
        {
            
            if (getx(pos) == 1 || gety(pos) == 1)
            {
                return true;
            }
            return false;
        }
        private bool isgoodsecondline(int pos)
        {
            if (issecondline(pos) && Group.getLibertyCount_full(pos, this, 2) < 3)
            {
                foreach (int nei in Group.getNeighbors(pos, myboardsize).Keys)
                {
                    if (myGroupPosition.ContainsKey(nei))
                    {
                        if (myGroup[myGroupPosition[nei]].myColor != mytoMove)
                        {
                            if (myGroup[myGroupPosition[nei]].myLibs.Count <= Group.getLibertyCount_full(pos, this, myGroup[myGroupPosition[nei]].myLibs.Count))
                            {
                                
                                return true;
                            }
                        }
                    }
                }
                return false;
            }
            return true;
        }
       
        public bool isEmptyTriangle(int pos)
        {
            neis.Clear();
            opps.Clear();
            bool et = false;
            // trick to only get empty triangles
            foreach (int cpos in Group.getNeighbors(pos, myboardsize).Keys)
            {
                if (!myGroupPosition.ContainsKey(cpos))
                {
                    opps.Add(cpos);
                    continue;
                }
                if (myGroup[myGroupPosition[cpos]].myColor == mytoMove)
                {
                    if (neis.Values.Contains(myGroup[myGroupPosition[cpos]].myposition))
                    {
                        return true;
                    }
                    neis[cpos] = myGroup[myGroupPosition[cpos]].myposition;
                }
            }
            if (neis.Count > 0)
            {
                foreach (int free in opps)
                {
                    foreach (int a in neis.Values)
                    {
                        if (myGroup[a].myLibs.ContainsKey(free))
                        {
                            et = true;
                            break;
                        }
                    }
                    if (et == true) break;
                }
            }
            if (neis.Count == 2)
            {
                int freepos = -pos;
                foreach (int key in neis.Keys) freepos += key;
                if (freepos != pos && !myGroupPosition.ContainsKey(freepos))
                {
                    return true;
                }
            }

            return et;
        }
        public static Dictionary<int, int> m = new Dictionary<int, int>();
        public bool ispotentialeye(int pos)
        {
            m.Clear();
            foreach (int cpos in Group.getNeighbors(pos, myboardsize).Keys)
            {

                if (!myGroupPosition.ContainsKey(cpos))
                {
                    return false;
                }
                if (myGroup[myGroupPosition[cpos]].myColor != mytoMove)
                {
                    return false;
                }
                if (!m.ContainsKey(myGroupPosition[cpos]))
                {
                    m[myGroupPosition[cpos]] = myGroupPosition[cpos];
                }

            }
            int noeye = 0;
            foreach (int c in Group.getNeighbors_rad_no_cache(pos, this, 1).Values)
            {
                if (myGroup[c].myColor != mytoMove)
                {
                    if (myGroup[c].myLibs.Count == 1)
                        
                    {
                        continue;
                    }

                    ++noeye;
                    if (noeye > 1 || isfirstline(pos))
                    {
                        removeFromPotential(pos, m);
                        return false;
                    }
                }
            }
            //foreach (int g in m)
            //{
            //    if (!myGroup[g].mypotEye.ContainsKey(pos))
            //    {
            //        myGroup[g].mypotEye[pos] = pos;
            //    }
            //}
            return true;
        }

        private void removeFromPotential(int pos, Dictionary<int,int> m)
        {
            foreach (int g in m.Keys)
            {
                if (myGroup[g].mypotEye.ContainsKey(pos))
                {
                    myGroup[g].mypotEye.Remove(pos);
                }
            }
        }

        private bool isSelfAtatri(int pos)
        {
            if (mymovehistory.Count > myboardsize * myboardsize / 3 * 2) return false; 
            if (Group.getLibertyCount_full(pos, this, 1) == 1)
            {
                neis.Clear();
                Group own = null;
                int fieldcount = 1;
                foreach(int nei in Group.getNeighbors(pos,myboardsize).Keys)
                {
                    if (myGroupPosition.ContainsKey(nei))
                    {
                        if(myGroup[myGroupPosition[nei]].myColor == mytoMove)
                        {
                            own = myGroup[myGroupPosition[nei]];
                            fieldcount += myGroup[myGroupPosition[nei]].myFields.Count;
                            if (fieldcount > 5)
                            {
                                return true;
                            }
                        }
                        else
                        {
                            neis[myGroupPosition[nei]] = myGroupPosition[nei];
                        }

                    }
                }
                if (own != null)
                {
                    int pot = 0;
                    foreach(int nei in neis.Keys)
                    {
                        pot += myGroup[nei].myEyes.Count * 5;
                        pot += myGroup[nei].mypotEye.Count*2;
                        pot += myGroup[nei].myLibs.Count - 1;
                        if (pot > 9)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        private bool isOverconcentrated(int pos)
        {
            if (mymovehistory.Count > myboardsize*myboardsize/3) return false;
            bool isGroupNear = false;
            foreach (int nei in Group.getNeighbors(pos, myboardsize).Keys)
            {
                if (myGroupPosition.ContainsKey(nei))
                {
                    isGroupNear = true;
                    if (myGroup[myGroupPosition[nei]].myColor != mytoMove)
                    {
                        return false;
                    }
                    foreach(int nei1 in myGroup[myGroupPosition[nei]].myNeighbors.Keys)
                    {
                        if (myGroupPosition.ContainsKey(nei1))
                        { 
                            if (myGroup[myGroupPosition[nei1]].myLibs.Count <= myGroup[myGroupPosition[nei]].myLibs.Count +1)
                            {
                                return false;
                            }
                        }
                    }
                }

            }
            if (isGroupNear)
            {
                //++randmovescount;
                return true;
            }
            return false;
            
        }
        private bool isSekiLib(int pos)
        {
            return false;
            //if (Tree.myRootBoard.mytoMove == color.white) return false;
            List<int> theList = new List<int>();
            foreach (int cpos in Group.getNeighbors(pos, myboardsize).Keys)
            {
                if (!myGroupPosition.ContainsKey(cpos)) continue;
                if (!theList.Contains(myGroupPosition[cpos])) theList.Add(myGroupPosition[cpos]);
                if (theList.Count > 2)
                {
                    return false;
                }
            }
            if (theList.Count < 2)
            {
                return false;
            }
            Group own = null;
            Group opp = null;

            foreach (int cpos in theList)
            {
                if (myGroup[cpos].myColor == mytoMove)
                {
                    own = myGroup[cpos];
                }
                else
                {
                    opp = myGroup[cpos];
                }
            }
            if (opp == null || own == null)
            {
                return false;
            }
            if (opp.myEyes.Count > 1 || own.myEyes.Count > 1 || opp.myLibs.Count > 2 || own.myLibs.Count > 2)
            {
                return false;
            }
            if (opp.myEyes.Count != own.myEyes.Count)
            {
                return false;
            }
            if (own.myFields.Count < 6 || opp.myFields.Count < 6)
            {
                return false;
            }
            foreach (int libpos in own.myLibs.Keys)
            {
                if (!opp.myLibs.ContainsKey(libpos))
                {
                    return false;
                }
            }
            foreach (int libpos in opp.myLibs.Keys)
            {
                if (!own.myLibs.ContainsKey(libpos))
                {
                    return false;
                }
                foreach (int nei in Group.getNeighbors(libpos, myboardsize).Keys)
                {
                    if (myGroupPosition.ContainsKey(nei))
                    {
                        if (myGroupPosition[nei] != own.myposition && myGroupPosition[nei] != opp.myposition)
                        {
                            return false;
                        }
                    }
                    else
                    {
                        if (!own.myLibs.ContainsKey(nei))
                        {
                            return false;
                        }
                    }
                }
            }
            //++randmovescount;
            return true;
        }


    }
}
